package org.domeos.framework.api.service.project.impl;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.domeos.basemodel.HttpResponseTemp;
import org.domeos.basemodel.ResultStat;
import org.domeos.client.kubernetesclient.definitions.v1.EnvVar;
import org.domeos.client.kubernetesclient.definitions.v1beta1.Job;
import org.domeos.exception.RSAKeypairException;
import org.domeos.exception.WebHooksException;
import org.domeos.framework.api.biz.OperationHistory;
import org.domeos.framework.api.biz.global.GlobalBiz;
import org.domeos.framework.api.biz.project.ProjectBiz;
import org.domeos.framework.api.controller.exception.ApiException;
import org.domeos.framework.api.controller.exception.PermitException;
import org.domeos.framework.api.model.ci.BuildHistory;
import org.domeos.framework.api.model.ci.CodeType;
import org.domeos.framework.api.model.ci.related.*;
import org.domeos.framework.api.model.global.Registry;
import org.domeos.framework.api.model.image.BaseImage;
import org.domeos.framework.api.model.operation.OperationRecord;
import org.domeos.framework.api.model.operation.OperationType;
import org.domeos.framework.api.model.project.Project;
import org.domeos.framework.api.model.project.SubversionUser;
import org.domeos.framework.api.model.project.related.*;
import org.domeos.framework.api.model.resource.related.ResourceType;
import org.domeos.framework.api.service.image.impl.PrivateRegistry;
import org.domeos.framework.api.service.project.BuildService;
import org.domeos.framework.engine.AuthUtil;
import org.domeos.framework.engine.coderepo.CodeApi;
import org.domeos.framework.engine.coderepo.GitWebHook;
import org.domeos.framework.engine.coderepo.CodeApis;
import org.domeos.framework.engine.coderepo.WebHook;
import org.domeos.framework.engine.exception.DaoException;
import org.domeos.framework.engine.k8s.JobWrapper;
import org.domeos.global.CurrentThreadInfo;
import org.domeos.global.GlobalConstant;
import org.domeos.util.CommonUtil;
import org.domeos.util.RSAKeyPairGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Created by feiliu206363 on 2015/7/29.
 */
@Service("buildService")
public class BuildServiceImpl implements BuildService {

    private static Logger logger = Logger.getLogger(BuildServiceImpl.class);

    @Autowired
    ProjectBiz projectBiz;
    @Autowired
    GlobalBiz globalBiz;
    @Autowired
    OperationHistory operationHistory;

    public void checkOperatePermission(int id) {
        AuthUtil.verify(CurrentThreadInfo.getUserId(), id, ResourceType.PROJECT, OperationType.GET);
    }

    public void checkModifiable(int id) {
        AuthUtil.verify(CurrentThreadInfo.getUserId(), id, ResourceType.PROJECT, OperationType.MODIFY);
    }

    public void checkDeletable(int id) {
        AuthUtil.verify(CurrentThreadInfo.getUserId(), id, ResourceType.PROJECT, OperationType.DELETE);
    }

    @Override
    public HttpResponseTemp<?> dockerfilePreview(Project project) {
        if (project == null) {
            throw ApiException.wrapMessage(ResultStat.PARAM_ERROR, "input project info is null");
        }
        checkOperatePermission(project.getId());

        if (project.getDockerfileConfig() != null && project.getDockerfileInfo() == null) {
            if (!StringUtils.isBlank(project.getDockerfileConfig().checkLegality())) {
                throw ApiException.wrapMessage(ResultStat.PARAM_ERROR, project.getDockerfileConfig().checkLegality());
            }
            DockerfileContent dockerfile = project.getDockerfileConfig();
            if (dockerfile == null) {
                throw ApiException.wrapMessage(ResultStat.PARAM_ERROR, "docker file config is null");
            }

            try {
                String dockerfileStr = generateDockerFile(dockerfile, project.getConfFiles());
                return ResultStat.OK.wrap(dockerfileStr);
            } catch (Exception e) {
                throw ApiException.wrapUnknownException(e);
            }
        } else if (project.getDockerfileConfig() == null && project.getDockerfileInfo() != null) {
            UserDefinedDockerFile dockerfileInfo = project.getDockerfileInfo();
            CodeConfiguration codeInfo = project.getCodeInfo();
            if (codeInfo == null) {
                throw ApiException.wrapMessage(ResultStat.PARAM_ERROR, "code info is null");
            }
            CodeApi codeApi = CodeApis.createCodeApi(CodeType.getByName(codeInfo.getCodeManager()),
                    codeInfo.getCodeManagerUserId());
            if (codeApi == null) {
                throw ApiException.wrapMessage(ResultStat.PARAM_ERROR, "get code api error");
            }
            String dockerfilePath = dockerfileInfo.getDockerfilePath();
            if (!StringUtils.isBlank(dockerfilePath) && dockerfilePath.startsWith("/")) {
                dockerfilePath = dockerfilePath.substring(1);
            }
            String dockerfileStr = codeApi.getDockerFile(codeInfo.getCodeId(), dockerfileInfo.getBranch(), dockerfilePath);
            return ResultStat.OK.wrap(dockerfileStr);
        } else {
            throw ApiException.wrapMessage(ResultStat.PARAM_ERROR, "docker config and docker info both exist");
        }
    }

    @Override
    public String dockerFile(int projectId, int buildId, String secret) {
        String docker = null;
        String buildSecret = projectBiz.getSecretById(buildId);
        if (buildSecret == null || !buildSecret.equals(secret)) {
            return "Forbidden";
        }
        try {
            Project project = projectBiz.getById(GlobalConstant.PROJECT_TABLE_NAME, projectId, Project.class);
            if (project != null) {
                docker = generateDockerFile(project.getDockerfileConfig(), project.getConfFiles());
            }
        } catch (Exception e) {
            throw ApiException.wrapUnknownException(e);
        }
        return docker;
    }

    @Override
    public HttpResponseTemp<?> dockerfileUsed(int projectId, int buildId) {
        checkOperatePermission(projectId);

        return ResultStat.OK.wrap(projectBiz.getDockerFileByBuildId(buildId));
    }

    @Override
    public HttpResponseTemp<?> startAutoBuild(String webHookStr) {
        try {
            WebHook webHook = new GitWebHook(webHookStr);

            Project project = projectBiz.getById(webHook.getProject_id());

            String imageTag = null;

            if(project!=null){
                AutoBuild autoBuild = project.getAutoBuildInfo();
                if (autoBuild!=null&&autoBuild.getTag() == 1 && !StringUtils.isBlank(webHook.getTag())) {
                    imageTag = webHook.getTag();
                }
                if (autoBuild.getBranches() != null) {
                    for (String branch : autoBuild.getBranches()) {
                        if (branch.equals(webHook.getBranch())) {
                            imageTag = webHook.getBranch() + "_" + webHook.getAfter().substring(0, 7);
                            break;
                        }
                    }
                }
            }

            CodeInfomation codeInfo = new CodeInfomation();
            codeInfo.setCodeBranch(webHook.getBranch());
            codeInfo.setCodeTag(webHook.getTag());

            CommitInformation commitInfo = new CommitInformation();
            commitInfo.setId(webHook.getAfter());
            commitInfo.setName(webHook.getRepositoryName());
            commitInfo.setMessage(webHook.getCommitMessage());
            commitInfo.setAuthoredDate(0);
            commitInfo.setAuthorName(webHook.getUser_name());
            commitInfo.setAuthorEmail(webHook.getUser_email());
            commitInfo.setCommittedDate(webHook.getCommitTimestamp());
            commitInfo.setCommitterName(webHook.getCommitAuthorName());
            commitInfo.setCommitterEmail(webHook.getCommitAuthorEmail());

            ImageInformation imageInfo = new ImageInformation();
            imageInfo.setImageName(project.getName());
            imageInfo.setImageTag(imageTag);
            imageInfo.setRegistry(globalBiz.getRegistry().registryDomain());

            BuildHistory buildInfo = new BuildHistory()
                    .checkLegality()
                    .withCommitInfo(commitInfo)
                    .withImageInfo(imageInfo)
                    .withCodeInfo(codeInfo)
                    .withAutoBuild(1);

            HttpResponseTemp<?> result = sendBuildJob(buildInfo, project);
            if (result != null) {
                return result;
            }

        } catch (WebHooksException e) {
            logger.warn("webhook error, message is " + e.getMessage());
            throw ApiException.wrapMessage(ResultStat.WEBHOOK_ERROR, e.getMessage());
        } catch (RSAKeypairException e) {
            logger.warn("rsa keypair error, message is " + e.getMessage());
            throw ApiException.wrapMessage(ResultStat.RSAKEYPAIR_ERROR, e.getMessage());
        } catch (DaoException e) {
            logger.warn("dao exception, message is " + e.getMessage());
            throw ApiException.wrapUnknownException(e);
        }
        return ResultStat.OK.wrap(null);
    }

    @Override
    public HttpResponseTemp<?> startBuild(BuildHistory buildInfo) {

        checkOperatePermission(buildInfo.getProjectId());

        Project project = projectBiz.getById(buildInfo.getProjectId());

        buildInfo.checkLegality()
            .withCommitInfo(fetchCommitRecordFromApi(project,buildInfo))
            .withImageInfo(buildImageInfo(buildInfo, project))
            .withUserInfo(buildUserInformation())
            .withState(BuildState.Preparing);

        try {
            sendBuildJob(buildInfo, project);
        } catch (DaoException e) {
            throw ApiException.wrapUnknownException(e);
        } catch (RSAKeypairException e) {
            logger.warn("rsa keypair error, " + e.getMessage());
            throw ApiException.wrapMessage(ResultStat.SERVER_INTERNAL_ERROR, e.getMessage());
        }

        operationHistory.insertRecord(new OperationRecord(buildInfo.getProjectId(), ResourceType.PROJECT, OperationType.BUILD, "JOBSEND", ""));

        return ResultStat.OK.wrap(buildInfo);
    }

    private ImageInformation buildImageInfo(BuildHistory buildInfo, Project project) {
        ImageInformation imageInfo = buildInfo.getImageInfo();
        if (buildInfo.getImageInfo() == null) {
            imageInfo = new ImageInformation();
        }

        imageInfo.setImageName(project.getName());
        imageInfo.setRegistry(globalBiz.getRegistry().registryDomain());

        if (StringUtils.isBlank(imageInfo.getImageTag())) {
            if (!StringUtils.isBlank(buildInfo.getCodeInfo().getCodeBranch())) {
                if (project.getCodeInfo() != null && project.getCodeInfo().getCodeManager() == CodeManager.subversion) {
                    imageInfo.setImageTag(buildInfo.getCodeInfo().getCodeBranch());
                } else {
                    imageInfo.setImageTag(buildInfo.getCodeInfo().getCodeBranch() + "_" + buildInfo.getCommitInfo().getId().substring(0, 7));
                }
            } else if (!StringUtils.isBlank(buildInfo.getCodeInfo().getCodeTag())) {
                imageInfo.setImageTag(buildInfo.getCodeInfo().getCodeTag());
            }
        }
        return imageInfo;
    }

    private CommitInformation fetchCommitRecordFromApi(Project project, BuildHistory buildInfo) {

        CommitInformation commitInfo = null;

        CodeConfiguration codeConfig = project.getCodeInfo();

        if (project.configCodeRepository()) {
            CodeApi codeApi = CodeApis.createCodeApi(codeConfig);
            if (codeApi != null) {
                commitInfo = codeApi.getCommitInfo(codeConfig.getCodeId(), "");
                CodeInfomation codeInfo = buildInfo.getCodeInfo();
                if (codeInfo.getCodeBranch() != null && !codeInfo.getCodeBranch().isEmpty()) {
                    commitInfo = codeApi.getBranchCommitInfo(codeConfig.getCodeId(), codeInfo.getCodeBranch());
                } else if (codeInfo.getCodeTag() != null && !codeInfo.getCodeTag().isEmpty()) {
                    commitInfo = codeApi.getTagCommitInfo(codeConfig.getCodeId(), codeInfo.getCodeTag());
                }
                if (commitInfo == null) {
                    throw ApiException.wrapMessage(ResultStat.GITLAB_COMMIT_NOT_FOUND, "cannot found commit info in gitlab, url: " + codeConfig.getCodeSshUrl());
                }
            }
        }
        return commitInfo;
    }

    private UserInformation buildUserInformation() {
        UserInformation userInfo = new UserInformation();
        userInfo.setUserId(CurrentThreadInfo.getUserId());
        userInfo.setUserName(AuthUtil.getUserNameById(CurrentThreadInfo.getUserId()));
        return userInfo;
    }

    @Override
    public HttpResponseTemp<?> setBuildStatus(BuildResult buildResult, String secret) throws DaoException {
        if (buildResult != null) {
            String buildSecret = projectBiz.getSecretById(buildResult.getBuildId());
            if (buildSecret == null || !buildSecret.equals(secret)) {
                throw new PermitException("secret not match");
            }
            BuildHistory buildInfo = projectBiz.getById(GlobalConstant.BUILDHISTORY_TABLE_NAME, buildResult.getBuildId(), BuildHistory.class);
            Registry registry = globalBiz.getRegistry();
            if (registry != null && BuildState.Success.name().equals(buildResult.getStatus())) {
                BaseImage baseImage = new BaseImage(buildInfo.getImageInfo().getImageName(),
                        buildInfo.getImageInfo().getImageTag(), registry.fullRegistry(), null);
                double imageSize = PrivateRegistry.getImageSize(baseImage);
                if (imageSize > 0) {
                    buildInfo.getImageInfo().setImageSize(imageSize);
                }
            }
            buildInfo.setFinishTime(System.currentTimeMillis());
            buildInfo.setState(buildResult.getStatus());

            projectBiz.updateBuildHistory(buildInfo);
        }
        return ResultStat.OK.wrap(null);
    }

    @Override
    public String downloadRsa(int projectId, int buildId, String secret) {
        String buildSecret = projectBiz.getSecretById(buildId);
        if (buildSecret == null || !buildSecret.equals(secret)) {
            return "Forbidden";
        }

        RSAKeyPair rsaKeyPair = projectBiz.getRSAKeyPairByProjectId(projectId);
        if (rsaKeyPair != null) {
            return rsaKeyPair.getPrivateKey();
        }
        return null;
    }

    @Override
    public HttpResponseTemp<?> uploadLogfile(MultipartFile body, int projectId, int buildId, String secret) {
        if (body == null) {
            throw ApiException.wrapMessage(ResultStat.PARAM_ERROR, "upload build log error");
        }

        try {
            byte[] bytes = new byte[(int) body.getSize()];
            body.getInputStream().read(bytes);
            projectBiz.insertBuildLogById(buildId, bytes);
        } catch (IOException e) {
            logger.error("save upload build log file error, message is " + e.getMessage());
        }
        return ResultStat.OK.wrap(null);
    }

    @Override
    public HttpResponseTemp<?> downloadLogFile(int projectId, int buildId) {
        checkOperatePermission(projectId);
        String log = projectBiz.getBuildLogById(buildId);
        return ResultStat.OK.wrap(log);
    }

    @Override
    public HttpResponseTemp<?> listBuildInfo(int projectId) {
        checkOperatePermission(projectId);
        try {
            List<BuildHistory> buildInfos = UpdateBuildStatusInfo.updateStatusInfos(projectBiz.getBuildHistoryByProjectId(projectId));
            return ResultStat.OK.wrap(buildInfos);
        } catch (Exception e) {
            throw ApiException.wrapUnknownException(e);
        }
    }

    public String generateDockerFile(DockerfileContent info, Map<String, String> configFiles)  {
        StringBuilder dockerFile = new StringBuilder();
        if (info != null) {
            String dockerFrom = CommonUtil.domainUrl(info.getBaseImageRegistry());
            if (!StringUtils.isBlank(dockerFrom)) {
                dockerFrom += "/";
            }
            dockerFrom += info.getBaseImageName();
            if (!StringUtils.isBlank(info.getBaseImageTag())) {
                dockerFrom += ":" + info.getBaseImageTag();
            }
            if (dockerFrom.startsWith(GlobalConstant.HTTP_PREFIX)) {
                dockerFrom = dockerFrom.substring(7);
            }
            if (dockerFrom.startsWith(GlobalConstant.HTTPS_PREFIX)) {
                dockerFrom = dockerFrom.substring(8);
            }
            dockerFile.append("From ").append(dockerFrom).append("\n");
            String env = checkEnv(info.getCompileEnv());
            if (!StringUtils.isBlank(env)) {
                dockerFile.append(env).append("\n");
            }
            if (!StringUtils.isBlank(info.getUser())) {
                dockerFile.append("USER ").append(info.getUser()).append("\n");
            }
            String command1 = checkCommand(info.getInstallCmd());
            if (!StringUtils.isBlank(command1)) {
                dockerFile.append("RUN ").append(command1).append("\n");
            }
            dockerFile.append("COPY . ").append(info.getCodeStoragePath()).append("\n");
            if (configFiles != null && configFiles.size() > 0) {
                dockerFile.append("COPY dockerize /usr/bin/dockerize\n");
            }
            dockerFile.append("WORKDIR ").append(info.getCodeStoragePath()).append("\n");
            String command2 = checkCommand(info.getCompileCmd());
            if (!StringUtils.isBlank(command2)) {
                dockerFile.append("RUN ").append(command2).append("\n");
            }
            if (!StringUtils.isBlank(info.getWorkDir())) {
                dockerFile.append("WORKDIR ").append(info.getWorkDir()).append("\n");
            }
            String cmd = info.getStartCmd();
            if (!StringUtils.isBlank(cmd)) {
                dockerFile.append("CMD");
                if (configFiles != null && configFiles.size() > 0) {
                    dockerFile.append(" dockerize");
                    for (Map.Entry<String, String> entry : configFiles.entrySet()) {
                        dockerFile.append(" -template ").append(entry.getKey()).append(":").append(entry.getValue());
                    }
                }
                dockerFile.append(" ").append(cmd).append("\n");
            }
        }
        return dockerFile.toString();
    }

    private String checkEnv(String envs) {
        StringBuilder result = new StringBuilder();
        if (!StringUtils.isBlank(envs)) {
            String[] pair = envs.split(",");
            for (String env : pair) {
                String[] info = env.split("=");
                result.append("ENV ").append(info[0]).append(" ").append(info[1]).append("\n");
            }
        }
        return result.toString();
    }

    private String checkCommand(String command) {
        StringBuilder result = new StringBuilder();
        if (!StringUtils.isBlank(command)) {
            if (command.startsWith("RUN ")) {
                result.append(command);
            } else {
                String[] ss = command.split("\n");
                for (String tmp : ss) {
                    if (result.length() > 0) {
                        result.append(" && ");
                    }
                    result.append(tmp);
                }
            }
        }
        return result.toString();
    }

    private HttpResponseTemp<Object> sendBuildJob(BuildHistory buildInfo, Project project) throws DaoException, RSAKeypairException {

        CodeConfiguration codeConfig = project.getCodeInfo();

        CodeApi codeApi = CodeApis.createCodeApi(codeConfig);

        String privateKey = codeApi.fetchPrivateKey(projectBiz,project,codeConfig);

        String buildPath = null;
        String dockerFilePath = null;

        if(project.isUserDefineDockerfile()){

            String ref = buildRef(buildInfo);

            UserDefinedDockerFile dockerFileInfo = project.getDockerfileInfo();

            buildPath = codeApi.obtainBuildPath(dockerFileInfo,buildInfo,project,ref);

            dockerFilePath =  codeApi.obtainDockerFilePath(dockerFileInfo,buildInfo,project,ref);

            buildInfo.setDockerfileContent(codeApi.getDockerFile(codeConfig.getCodeId(), ref, buildPath));

        }else{
            buildInfo.setDockerfileContent(generateDockerFile(project.getDockerfileConfig(), project.getConfFiles()));
        }

        buildInfo.setSecret(UUID.randomUUID().toString());

        projectBiz.saveBuildHistory(buildInfo);

        JobWrapper jobWrapper;
        try {
            jobWrapper = new JobWrapper().init();
        } catch (Exception e) {
            throw ApiException.wrapUnknownException(e);
        }

        EnvVar[] envVars = generateEnvs(codeConfig, buildInfo, privateKey, project.isUserDefineDockerfile(), buildPath, dockerFilePath);

        Job job = jobWrapper.generateJob(globalBiz.getBuildImage(), envVars);

        jobWrapper.sendJob(job);

        buildInfo.setTaskName(job.getMetadata().getName());
        buildInfo.setState(BuildState.Send.name());

        projectBiz.updateTaskNameAndStatus(buildInfo);

        return null;
    }

    private String buildRef(BuildHistory buildInfo) {
        String ref = null;
        if (!StringUtils.isBlank(buildInfo.getCodeInfo().getCodeTag()) && buildInfo.getCommitInfo() != null) {
            ref = buildInfo.getCommitInfo().getId();
        } else if (!StringUtils.isBlank(buildInfo.getCodeInfo().getCodeBranch())) {
            ref = buildInfo.getCodeInfo().getCodeBranch();
        }
        return ref;
    }

    public String getGitPrivateKey(CodeApi codeApi, int codeId, int projectId, String projectName)
            throws DaoException, RSAKeypairException {
        String privateKey = null;
        ProjectRsakeyMap keyMap = projectBiz.getRSAKeypairMapByProjectId(projectId);
        if (keyMap == null || !codeApi.checkDeployKey(codeId, keyMap.getKeyId())) {
            projectBiz.deleteRSAKeypairMapByProjectId(projectId);
            RSAKeyPair keyPair = RSAKeyPairGenerator.generateKeyPair();
            if (keyPair == null) {
                throw new RSAKeypairException("generate rsa key pair error");
            }
            int keyId = codeApi.setDeployKey(codeId, "DomeOS_" + projectName, keyPair.getPublicKey());
            if (keyId > 0) {
                keyPair.setCreateTime(System.currentTimeMillis());
                projectBiz.insertRowForRsaKeypair(keyPair);
                ProjectRsakeyMap projectRsakeyMap = new ProjectRsakeyMap();
                projectRsakeyMap.setProjectId(projectId);
                projectRsakeyMap.setRsaKeypairId(keyPair.getId());
                projectRsakeyMap.setKeyId(keyId);
                projectRsakeyMap.setCreateTime(System.currentTimeMillis());
                projectRsakeyMap.setState("active");
                projectBiz.addProjectRsaMap(projectRsakeyMap);
                System.out.println(keyPair.getPrivateKey());
                privateKey = keyPair.getPrivateKey().replaceAll("\n", "\\\\n");
            }
        } else {
            RSAKeyPair keyPair = projectBiz.getById(GlobalConstant.RSAKEYPAIR_TABLE_NAME, keyMap.getRsaKeypairId(), RSAKeyPair.class);
            privateKey = keyPair.getPrivateKey().replaceAll("\n", "\\\\n");
        }

        if (StringUtils.isBlank(privateKey)) {
            throw ApiException.wrapMessage(ResultStat.PARAM_ERROR, "put deploy key to git error, please check token");
        }

        return privateKey;
    }

    public EnvVar[] generateEnvs(CodeConfiguration codeConfig, BuildHistory buildInfo, String privateKey, boolean hasDockerFile, String buildPath, String dockerfilePath) {
        String commitId = null;
        if (buildInfo.getCommitInfo() != null) {
            commitId = buildInfo.getCommitInfo().getId();
        }
        return new EnvVar[]{
                new EnvVar().putName("SERVER").putValue(globalBiz.getServer().serverInfo()),
                new EnvVar().putName("BUILD_ID").putValue(String.valueOf(buildInfo.getId())),
                new EnvVar().putName("IDRSA").putValue(privateKey),
                new EnvVar().putName("CODE_URL").putValue(codeConfig.getCodeSshUrl()),
                new EnvVar().putName("PROJECT_ID").putValue(String.valueOf(buildInfo.getProjectId())),
                new EnvVar().putName("REGISTRY_URL").putValue(buildInfo.getImageInfo().getRegistry()),
                new EnvVar().putName("IMAGE_NAME").putValue(buildInfo.getImageInfo().getImageName()),
                new EnvVar().putName("IMAGE_TAG").putValue(buildInfo.getImageInfo().getImageTag()),
                new EnvVar().putName("COMMIT_ID").putValue(commitId),
                new EnvVar().putName("HAS_DOCKERFILE").putValue(String.valueOf(hasDockerFile ? 1 : 0)),
                new EnvVar().putName("SECRET").putValue(buildInfo.getSecret()),
                new EnvVar().putName("BUILD_PATH").putValue(buildPath),
                new EnvVar().putName("DOCKERFILE_PATH").putValue(dockerfilePath),
                new EnvVar().putName("TYPE").putValue(codeConfig.getCodeManager().name())
        };
    }
}
